package com.duobaoyu.dby.supply.biz.strategy.message.refund;

import com.alibaba.fastjson.JSON;
import com.duobaoyu.dby.channel.adapter.bean.message.refund.AfterSaleStatusMessage;
import com.duobaoyu.dby.channel.adapter.enums.ChannelCodeEnum;
import com.duobaoyu.dby.channel.adapter.enums.biz.refund.AfterSaleStatusEnum;
import com.duobaoyu.dby.common.mybatis.util.EnumUtils;
import com.duobaoyu.dby.supply.biz.constant.OperateSourceConstants;
import com.duobaoyu.dby.supply.biz.enums.AfterSaleSourceEnum;
import com.duobaoyu.dby.supply.common.biz.bo.refund.AfterSaleOutBO;
import com.duobaoyu.dby.supply.common.biz.bo.refund.AfterSaleStateContext;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author yw
 * @description
 * @date 2023/10/13 17:22
 */
@Slf4j
@Component
public class DeliAfterSaleStatusAsyncHandler extends AbstractChannelAfterSaleStateChangeHandler {
    @Override
    protected Set<String> channelCodes() {
        return Sets.newHashSet(ChannelCodeEnum.DE_LI.getValue());
    }

    @Override
    protected Void handler(AfterSaleStateChangeMessageAsyncHandler.Context context,
                           Object beforeResult) {
        List<AfterSaleStatusMessage> channelAfterSaleMessages = context.getOriginMessages();
        List<AfterSaleOutBO> afterSaleItems = context.getAfterSales();
        Map<String, AfterSaleOutBO> afterSales = afterSaleItems.stream()
                .collect(Collectors.toMap(AfterSaleOutBO::getChannelAfterSaleSn, Function.identity(), (k1, k2) -> k1));

        List<AfterSaleStateContext> afterSaleStateContextList = Lists.newArrayList();
        List<AfterSaleStatusMessage> failureMessages = Lists.newArrayList();
        for (AfterSaleStatusMessage afterSaleMessage : channelAfterSaleMessages) {
            String channelAfterSaleSn = afterSaleMessage.getChannelAfterSaleSn();
            if (StringUtils.isBlank(channelAfterSaleSn)) {
                log.error("售后申请结果回调，无渠道售后编号,param={}", JSON.toJSON(afterSaleMessage));
                continue;
            }
            try {
                AfterSaleOutBO afterSale = afterSales.get(channelAfterSaleSn);

                Integer afterSaleStatus = afterSaleMessage.getAfterSaleStatus();
                if (EnumUtils.eq(AfterSaleStatusEnum.TO_BE_CONFIRMED_BY_USER, afterSaleStatus)
                        && EnumUtils.eq(AfterSaleSourceEnum.SYSTEM, afterSale.getAfterSaleSource())) {
                    afterSaleStatus = AfterSaleStatusEnum.COMPLETED.getValue();
                }

                BigDecimal refundAmount = afterSaleMessage.getRefundInfo().getRefundAmount();
                List<AfterSaleStateContext.AfterSaleUpdateItemInfo> afterSaleItemInfoList =
                        buildRefundInfo(refundAmount, null, afterSale);
                // 退款
                BigDecimal channelActualRefundAmount = null,
                        channelFreightActualRefundAmount = null;

                if (Objects.nonNull(refundAmount)) {
                    channelActualRefundAmount = afterSaleItemInfoList.stream().map(AfterSaleStateContext.AfterSaleUpdateItemInfo::getChannelActualRefundAmount)
                            .reduce(BigDecimal.ZERO, BigDecimal::add);
                    channelFreightActualRefundAmount = afterSaleItemInfoList.stream().map(AfterSaleStateContext.AfterSaleUpdateItemInfo::getChannelFreightActualRefundAmount)
                            .reduce(BigDecimal.ZERO, BigDecimal::add);
                }
                AfterSaleStateContext stateChange = new AfterSaleStateContext();
                stateChange.setAfterSale(afterSale);
                stateChange.setCurrentAfterSaleStatus(afterSaleStatus);
                stateChange.setChangeContentOperate(AfterSaleStateContext.ChangeContentOperate.builder()
                        .channelAfterSaleSn(afterSaleMessage.getChannelAfterSaleSn())
                        .afterSaleItemInfoList(afterSaleItemInfoList)
                        .failReason(afterSaleMessage.getFailReason())
                        .channelActualRefundAmount(channelActualRefundAmount)
                        .channelFreightActualRefundAmount(channelFreightActualRefundAmount)
                        .build());
                stateChange.setOperateSource(OperateSourceConstants.OPERATION_CHANNEL);
                afterSaleStateContextList.add(stateChange);
            } catch (Exception e) {
                failureMessages.add(afterSaleMessage);
            }
        }
        context.setHandleSuccessMessages(afterSaleStateContextList);
        context.setHandleFailureMessages(failureMessages);
        return null;
    }

//    private AfterSaleStateContext.RefundInfo buildRefundInfo(AfterSaleStatusMessage.RefundInfo channelRefundInfo, AfterSaleOutBO afterSale) {
//        if (channelRefundInfo == null || Objects.isNull(channelRefundInfo.getRefundAmount())) {
//            return null;
//        }
//        Money channelRealRefundAmount = new Money(channelRefundInfo.getRefundAmount());
//        // 订单取消
//        if (AfterSaleSourceEnum.SYSTEM.getValue().equals(afterSale.getAfterSaleSource())) {
//            Money itemTotalAmount = afterSale.getItems().stream().map(e -> new Money(e.getChannelActualPaidAmount()))
//                    .reduce(new Money(), Money::add);
//            final Money[] freightRefundAmount = {channelRealRefundAmount.subtract(itemTotalAmount)};
//            if (freightRefundAmount[0].compareTo(new Money()) < 0) {
//                SupplyChainBizException.fail("渠道退款金额小于商品实付金额");
//            }
//            List<AfterSaleStateContext.RefundItem> refundItems = afterSale.getItems().stream().map(item -> {
//                AfterSaleStateContext.RefundItem refundItem = new AfterSaleStateContext.RefundItem();
//                refundItem.setSkuCode(item.getSkuCode());
//                refundItem.setChannelActualRefundAmount(item.getChannelActualPaidAmount());
//                refundItem.setChannelFreightActualRefundAmount(freightRefundAmount[0].getAmount());
//                // 运费添加其中一个商品
//                freightRefundAmount[0] = freightRefundAmount[0].subtract(freightRefundAmount[0]);
//                return refundItem;
//            }).collect(Collectors.toList());
//            AfterSaleStateContext.RefundInfo refundInfo = new AfterSaleStateContext.RefundInfo();
//            refundInfo.setRefundAmount(channelRealRefundAmount.getAmount());
//            refundInfo.setFreightRefundAmount(freightRefundAmount[0].getAmount());
//            refundInfo.setItems(refundItems);
//            return refundInfo;
//        } else {
//            AfterSaleItemOutBO first = CollUtil.getFirst(afterSale.getItems());
//            boolean existFreightRefund = channelRealRefundAmount.compareTo(new Money(afterSale.getApplyRefundAmount()))
//                    > CommonConstants.ZERO;
//            AfterSaleStateContext.RefundItem refundItem = new AfterSaleStateContext.RefundItem();
//            refundItem.setSkuCode(first.getSkuCode());
//            refundItem.setChannelActualRefundAmount(existFreightRefund ? afterSale.getApplyRefundAmount() :
//                    channelRealRefundAmount.getAmount());
//            refundItem.setChannelFreightActualRefundAmount(existFreightRefund ?
//                    channelRealRefundAmount.subtract(new Money(refundItem.getChannelActualRefundAmount())).getAmount()
//                    : BigDecimal.ZERO);
//
//            AfterSaleStateContext.RefundInfo refundInfo = new AfterSaleStateContext.RefundInfo();
//            refundInfo.setItems(Lists.newArrayList(refundItem));
//            refundInfo.setRefundAmount(refundInfo.getItems().stream().map(AfterSaleStateContext.RefundItem::
//                    getChannelActualRefundAmount).reduce(BigDecimal.ZERO, BigDecimal::add));
//            refundInfo.setFreightRefundAmount(refundInfo.getItems().stream().map(AfterSaleStateContext.RefundItem::
//                    getChannelFreightActualRefundAmount).reduce(BigDecimal.ZERO, BigDecimal::add));
//            return refundInfo;
//        }
//    }
}
